package com.jnzc.ocr.serv.shop.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.collect.Lists;
import com.jnzc.ocr.common.utils.BusinessUtils;
import com.jnzc.ocr.common.utils.CalculateUtils;
import com.jnzc.ocr.common.utils.DateUtils;
import com.jnzc.ocr.common.utils.ValidateUtils;
import com.jnzc.ocr.dependencies.serv.mybatis.MybatisServiceImpl;
import com.jnzc.ocr.serv.shop.consts.ShopOrderConsts;
import com.jnzc.ocr.serv.shop.consts.ShopRefundConsts;
import com.jnzc.ocr.serv.shop.entity.*;
import com.jnzc.ocr.serv.shop.filter.ShopRefundSaleFilter;
import com.jnzc.ocr.serv.shop.helper.ShopOrderSaleHelper;
import com.jnzc.ocr.serv.shop.helper.ShopRefundSaleHelper;
import com.jnzc.ocr.serv.shop.mapper.ShopRefundSaleMapper;
import com.jnzc.ocr.serv.shop.service.*;
import com.jnzc.ocr.serv.shop.vo.ShopProductStockChangeVo;
import com.jnzc.ocr.serv.shop.vo.ShopRefundSaleCreateVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author zhangcm
 * @version 1.0, 2017-11-26
 */
@Service
public class ShopRefundSaleServiceImpl extends MybatisServiceImpl<ShopRefundSaleMapper, ShopRefundSale, ShopRefundSaleFilter> implements ShopRefundSaleService {

    @Autowired
    private ShopOrderService shopOrderService;

    @Autowired
    private ShopRefundService shopRefundService;

    @Autowired
    private ShopOrderSaleDetailService shopOrderSaleDetailService;

    @Autowired
    private ShopProductStockService shopProductStockService;

    @Autowired
    private ShopRefundSaleDetailService shopRefundSaleDetailService;

    @Override
    protected void fillEntityWrapper(EntityWrapper<ShopRefundSale> ew, ShopRefundSaleFilter filter) {
        ShopRefundSale entity = new ShopRefundSale();
        ew.setEntity(entity);
    }

    @Override
    @Transactional
    public ShopRefund create(ShopRefundSaleCreateVo createVo, Long shopId) {
        ValidateUtils.isId(createVo.getOrderId(), "订单ID");
        ValidateUtils.notNull(createVo.getIfBackStock(), "是否入库");
        ValidateUtils.notNull(createVo.getIfSign(), "是否退货");
        ValidateUtils.notNull(createVo.getBackType(), "退款类型");
        ValidateUtils.notNull(createVo.getBackMethod(), "退款方式");
        ValidateUtils.isId(shopId, "店铺ID");

        ShopOrder order = shopOrderService.find(createVo.getOrderId(), shopId);
        ShopRefundSaleHelper.check(order);
        Map<Long, ShopOrderSaleDetail> detailMap = shopOrderSaleDetailService.listSkuMap(order.getId());
        ShopRefundSaleHelper.checkDetail(createVo, detailMap);

        ShopRefundSale refundSale = new ShopRefundSale();
        refundSale.setShopId(shopId);
        refundSale.setIfBackStock(createVo.getIfBackStock());
        refundSale.setIfSign(createVo.getIfSign());
        refundSale.setBackType(createVo.getBackType());
        refundSale.setOrderAmount(order.getAmount());
        if(createVo.getBackType().equals(ShopRefundConsts.BACK_TYPE_ALL)) {
            refundSale.setChargingAmount(BigDecimal.ZERO);
        } else if(createVo.getBackType().equals(ShopRefundConsts.BACK_TYPE_CHARGING)) {
            BigDecimal chargingAmount = CalculateUtils.def(createVo.getChargingAmount());
            ValidateUtils.inRange(chargingAmount, true, BigDecimal.ZERO, order.getAmount(), "扣费金额不正确");
            refundSale.setChargingAmount(chargingAmount);
        }
        refundSale.setBackMethod(createVo.getBackMethod());

        List<ShopRefundSaleDetail> refundSaleDetailList = createRefundSaleDetail(createVo, refundSale, detailMap);
        BigDecimal totalRefundAmount = ShopRefundSaleHelper.getTotalRefundAmount(refundSaleDetailList);

        ShopRefund refund = new ShopRefund();
        refund.setShopId(shopId);
        refund.setOrderId(order.getId());
        refund.setType(ShopRefundConsts.TYPE_SALE);
        refund.setRefundAmount(CalculateUtils.sub(totalRefundAmount, refundSale.getChargingAmount()));
        refund.setCreateTime(DateUtils.getNow());
        shopRefundService.insertOne(refund);

        refundSale.setRefundId(refund.getId());
        this.insertOne(refundSale);

        for (ShopRefundSaleDetail refundSaleDetail : refundSaleDetailList) {
            refundSaleDetail.setRefundId(refund.getId());
        }
        shopRefundSaleDetailService.insertList(refundSaleDetailList);

        // 修改订单
        this.updateOrderSale(createVo, order, detailMap);
        // 修改库存
        if(refundSale.getIfBackStock()) {
            this.updateProductStock(createVo, detailMap, shopId);
        }
        return refund;
    }

    private void updateOrderSale(ShopRefundSaleCreateVo param, ShopOrder order, Map<Long, ShopOrderSaleDetail> detailMap) {
        // 更新销售订单详情
        List<ShopOrderSaleDetail> detailUpdateList = Lists.newArrayList();
        for (ShopRefundSaleCreateVo.Detail detailParam : param.getDetailList()) {
            ShopOrderSaleDetail detail = detailMap.get(detailParam.getSkuId());
            detail.setRefundNum(CalculateUtils.add(detail.getRefundNum(), detailParam.getNum()));
            detailUpdateList.add(detail);
        }
        shopOrderSaleDetailService.updateList(detailUpdateList);
        // 更新销售订单
        Integer totalRefundNum = ShopOrderSaleHelper.getTotalRefundNum(Lists.newArrayList(detailMap.values()));
        order.setIfRefund(totalRefundNum.equals(order.getNum()));
        order.setRefundNum(totalRefundNum);
        order.setRefundTime(DateUtils.getNow());
        shopOrderService.updateOne(order);
    }

    private void updateProductStock(ShopRefundSaleCreateVo param, Map<Long, ShopOrderSaleDetail> detailMap, Long shopId) {
        List<ShopProductStockChangeVo> stockChangeList = Lists.newArrayList();
        for (ShopRefundSaleCreateVo.Detail detailParam : param.getDetailList()) {
            ShopOrderSaleDetail detail = detailMap.get(detailParam.getSkuId());
            ShopProductStockChangeVo obj = new ShopProductStockChangeVo();
            obj.setProductId(detail.getProductId());
            obj.setSkuId(detail.getSkuId());
            obj.setAddStockNum(detailParam.getNum());
            obj.setAddSaleNum(CalculateUtils.neg(detailParam.getNum()));
            stockChangeList.add(obj);
        }
        shopProductStockService.updateNum(stockChangeList, shopId);
    }

    private List<ShopRefundSaleDetail> createRefundSaleDetail(ShopRefundSaleCreateVo param, ShopRefundSale refundSale, Map<Long, ShopOrderSaleDetail> detailMap) {
        List<ShopRefundSaleDetail> list = Lists.newArrayList();
        for (ShopRefundSaleCreateVo.Detail detailParam : param.getDetailList()) {
            ShopOrderSaleDetail detail = detailMap.get(detailParam.getSkuId());
            ShopRefundSaleDetail obj = new ShopRefundSaleDetail();
            obj.setShopId(refundSale.getShopId());
            obj.setRefundId(refundSale.getRefundId());
            obj.setProductId(detail.getProductId());
            obj.setProductName(detail.getProductName());
            obj.setSkuId(detail.getSkuId());
            obj.setSkuName(detail.getSkuName());
            obj.setProductCategoryId(detail.getProductCategoryId());
            obj.setRefundNum(detailParam.getNum());
            obj.setRefundAmount(ShopRefundSaleHelper.getRefundAmount(detail, detailParam.getNum()));
            list.add(obj);
        }
        return list;
    }
}
